/* Surreal Time
http://roguelikedevelopment.org/~rogueli/php/article/showArticle.php?path=development/TIMETRACKING/articles/&article=Sureal%20Time%20-%20Damian%20Bentley%20[Damian.Bentley@dsto.defence.gov.au].txt
*/

/* Surreal Time, Battle System, and other funky stuff*/

/*


*****
NOTE: Most of these comments are outdated and do not agree with the code.
*****

LevelController
	Controls a zlevel(used for dungeon levels)
	Can spawn monsters
	Can spawn treasure
	Contains data on the current zlevel
	All are part of a var/list/LevelControllers list, their index is the zlevel they are controlling
	Updated whenever someone Move()s or Teleport()s into/outof the level

TurnController
	Controls ALL actions that take time in combat-zones
	All mobs in a combat zone have a TurnController
	Players each have(or start with) their own
	All a level's monsters share a special TurnController(to start with)
	Any mobs within 16 tiles of each other have a common TurnController
	Monsters that come into 16 tiles range of a player are added to the player's TurnController
	Distances being equal, the monster picks at random which it is attached to
	AI is restricted by TurnController, but does not receive any info from it(eg, hunt TurnController's owner down)
	When two players get within 16 tiles of each other, they get a common TurnController
		Surreal Time comes into effect
	Turn controller does a sleep or spawn()ed loop to check for turn's desired moves
	When a player tries to move while near another player, the move is stored in a variable
	When the turn controller loop gets to them, it executes the move
	Move is executed by one of the CallProc procs.
	Has pcList, npcList
	pcWithMove

	AddMob(mob/M as mob)
		Adds mob to this TurnController.
		Remove mob from old TurnController
		Sets the players TurnController to src

	RemoveMob(mob/M as mob)
		Remove the mob from the controller
		If this is a non-monster controller, and no pcs are left, delete self
		If is a monster controller, never delete self

mob
	UpdateTurnController()
		Does checks to see if there are any other mobs nearby.
		If there's another player  nearby, src is AddMob()ed to the other's TurnController
		If there is no one nearby, but the controller has more pc members listed, call _
			TurnController.RemoveMob(src) and src.NewTurnController()
		Checks for closest PC nearby, adds to that TurnController
		If a PC moving finds any monsters within 16, Update the monster with their TurnController

*/




mob
	var
		tmp/TurnController/TurnController
		tmp/LevelController/LevelController
		combat=0 as num
	proc
		UpdateTurnController()
			for(var/mob/pc/P in range(16, src)-src)
				if(P.TurnController!=src.TurnController)
					src.TurnController.AddMob(P)
			var/mob/pc/P = locate() in range(16, src) - src
			if(!P && TurnController.pcList.len > 1)
				TurnController.RemoveMob(src)
				src.NewTurnController()
			for(var/mob/monster/M in range(16, src) + TurnController.npcList)
				M.UpdateTurnController()
		UpdateLevelController()
			var/LevelController/LC = LevelControllers[z]
			if(LC!=LevelController)
				LevelController=LC
				combat=LevelController.CombatAllowed
		NewTurnController()
			var/TurnController/TC = new()
			TC.AddMob(src)
			src.TurnController = TC
		NewDummyTurnController()
			var/TurnController/Dummy/TC = new()
			TC.AddMob(src)
			src.TurnController = TC
	New(loc)
		..()
		spawn(1)
			if(istype(src,/mob/pc))
				if(!TurnController)
					src.NewTurnController()
			else if(istype(src,/mob/monster))
				src.NewTurnController()
			else
				src.NewDummyTurnController()
				return

	pc
		proc
			ForceMove() //Possibly put some AI here in future
				src.Rest() //For now, just rest

	monster
		NewTurnController()
			spawn()
				var/LevelController/LC = LevelControllers[src.z]
				LC.MonsterController.AddMob(src)
		UpdateTurnController()
			var/list/closepcs = list()
			for(var/mob/pc/P in range(16, src))
				closepcs.Add(P)
			if(!closepcs.len)
				if(!istype(TurnController,/TurnController/MonsterController))
					src.NewTurnController()
				return
			var/closestdist=17
			var/closepcindex
			for(var/i=1,i<closepcs.len+1,i++)
				var/mob/pc/P = closepcs[i]
				var/dist = get_dist(src,P)
				if(dist < closestdist)
					closestdist = dist
					closepcindex=i
			var/mob/pc/P = closepcs[closepcindex]
			if(istype(src.TurnController,/TurnController/MonsterController))
				P.TurnController.AddMob(src)
			else if(!src.TurnController.pcList.Find(P))
				P.TurnController.AddMob(src)

